/*
 * Copyright (c) 2023, 2023,yzc.cn All rights reserved.
 *
 */
package cn.yzc;

/**
 * <p>Project: SpringPro - ProxyFactory</p>
 * <p>Powered by yzc On 2023-10-19 16:50:51</p>
 * <p>描述：<p>
 *
 * @author yzc [yzc0415@126.com]
 * @version 1.0
 * @since 17
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T>
 * <p>
 * 泛型：类型参数化 实现方式  1.在类定义时 在类名后面<T> 2.在静态方法上指定泛型  使用泛型前要先声明<T>
 */

/**
 * 泛型：类型参数化
 * 实现方式  1.在类定义时 在类名后面<T>
 *         2.在静态方法上指定泛型  使用泛型前要先声明<T>
 */

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理工厂类
 *
 * @param <T> 代理的目标类型
 */
public class ProxyFactory<T> {
    /**
     * 代理的目标对象
     */
    T target;

    /**
     * 创建代理实例时 传递目标对象
     * @param target
     */
    public ProxyFactory(T target) {
        this.target = target;
    }

    /**
     * 创建目标对象的代理类对象
     * @return
     */
    public T createProxy() {
        /**
         * newProxyInstance方法参数说明
         * ClassLoader loader 类加载器
         * Class<?>[] interfaces 代理类要实现的接口，即目标类实现的接口就是代理类要实现订单接口
         *  InvocationHandler h 代理类要做的工作
         */
        return (T) Proxy.newProxyInstance(getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     *
                     * @param proxy 代理实例
                     * @param method 要执行的目标方法
                     * @param args 目标方法的参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //增加横切逻辑的地方
                        //添加日志
                        System.out.println("开始订单日志");
                        //添加事务
                        System.out.println("开启事务");
                        //调用目标方法 target目标对象
                        Object obj = method.invoke(target, args);
                        //提交事务
                        System.out.println("提交事务");
                        System.out.println("保存订单成功");
                        return obj; //将执行目标方法的返回值 返回
                    }
                });
    }

}
